<?php

namespace App\Logic\Order\Form;

use App\Component\User;
use App\Core\Exception\DefaultException;
use App\Model\Account\CollectionAccountModel;
use App\Model\Order\OrderModel;
use App\Model\Order\OrderTaskModel;
use App\Model\Member\MemberModel;
use App\Util\ArrayHelper;
use App\Util\CommonHelper;
use EasySwoole\Component\Di;
use EasySwoole\ORM\DbManager;
use EasySwoole\EasySwoole\Logger;
use App\Event\Event;

/**
 * Class NotifyForm
 * @package App\Logic\Order\Form
 * @property OrderDataSet $notifyData
 */
class NotifyForm extends \App\Core\BaseForm
{

    public $notify_data;

    protected $_dataSet;

    protected $_orderModel;
    protected $_paymentModel;
    protected $_memberModel;

    protected $_shippingNoArr;

    public function rules()
    {
        return [
            'notify_data' => ['isArray', '回调参数'],
        ];
    }
    protected function getNotifyData()
    {
        if ($this->_dataSet === null) {
            $this->_dataSet = new OrderDataSet($this->notify_data);
        }
        return $this->_dataSet;
    }
    public function validate()
    {
        //生成验证器，方法自动读取rules方法返回的值数据
        $validator = $this->createValidator();
        if (!($check = $validator->validate($this->getAttributes()))) {
            throw new DefaultException($validator->getError()->__toString(), 600);
        }

        //开始校验回调数据
        if(empty($this->notifyData->get('out_trade_no'))){
            throw new DefaultException('订单号错误！');
        }
        if(empty($this->notifyData->get('total_fee'))){
            throw new DefaultException('支付金额错误！');
        }
        if(empty($this->notifyData->get('success_time'))){
            throw new DefaultException('支付时间错误！');
        }
        if(empty($this->notifyData->get('channel'))){
            throw new DefaultException('支付来源错误！');
        }
        if(empty($this->notifyData->get('payment_id'))){
            throw new DefaultException('支付方式ID错误！');
        }
        if(empty($this->notifyData->get('transaction_id'))){
            throw new DefaultException('支付付款编号错误！');
        }
        //校验订单号
        if (empty($this->getOrder())) {
            throw new DefaultException('订单不存在');
        }
        if ($this->getOrder()->pay_state == OrderModel::PAYSTATE_PAID) {
            //订单已支付直接返回成功
            return $this->success();
        }

        //判断金额
        if (intval(bcmul($this->getOrder()->amount, 100, 0)) <> ($this->notifyData->get('total_fee') + $this->notifyData->get('settlement_total_fee', 0))) {
            //金额不匹配
            throw new DefaultException('订单金额不匹配');
        }

        if ($this->notifyData->get('settlement_total_fee', 0) > $this->notifyData->get('total_fee')) {
            throw new DefaultException('回调数据出错');
        }

        if (!Di::getInstance()->get('user')) {
//            $userIdentity = WxappUser::findIdentity($this->getOrder()->mem_id);
//
//            $user = new User(WxappUser::class);
//            $user->login($userIdentity);
//
//            Di::getInstance()->set('user', $user);
        }

        return true;
    }

    /**
     * 支付回调 payNotify
     * @param NotifyForm $form
     * @return \App\Core\Output|true
     * @throws DefaultException
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public function payNotify()
    {
        $check = $this->validate();
        if ($check !== true) {
            return $check;
        }

        DbManager::getInstance()->startTransactionWithCount('write');
        try {
            $order_id = $this->getOrder()->id;
            OrderModel::getOne(['id' => $order_id])->lockForUpdate();
            //修改订单状态
            $updata = [
                'pay_state'      => OrderModel::PAYSTATE_PAID,
                'state'          => OrderModel::ORDERSTATE_FINISHED,
                'payment_id'     => $this->notifyData->get('payment_id'),
                'payment_name'   => $this->getPayment()->payment,
                'transaction_id' => $this->notifyData->get('transaction_id'),
                'pay_time'       => $this->notifyData->get('success_time', CommonHelper::currentTime()),
                'pay_amount'     => bcmul($this->notifyData->get('total_fee'), 0.01, 2)
            ];
            $map    = ['id' => $order_id, 'pay_state' => OrderModel::PAYSTATE_UNPAID];
            $res    = OrderModel::updateData($updata, $map);
            if ($res->lastQueryResult()->getAffectedRows() < 1) {
                throw new DefaultException('订单状态变更失败');
            }

            //添加支付记录
            $paymentData = [
                'order_id'       => $this->getOrder()->id,
                'user_id'        => $this->getOrder()->user_id,
                'transaction_id' => $this->notifyData->get('transaction_id'),
                'amount'         => bcdiv($this->notifyData->get('total_fee'), 100, 2),
                'payment_id'     => $this->notifyData->get('payment_id'),
                'payment_name'   => $this->getPayment()->payment,
                'channel'        => $this->notifyData->get('channel'),
                'result_content' => $this->notifyData->__toString(),
            ];
            $res         = OrderTaskModel::insertData($paymentData);

            Logger::getInstance()->info('支付数据处理完成');

            //处理会员VIP到期时间
            Event::getInstance()->hook(
                Event::EVENT_VIP_EXPIRE,
                [
                    'user_id' => $this->getOrder()->user_id,
                    'vip_id'  => $this->getOrder()->vip_id,
                ]
            );
            //升级VIP更新推荐表数据
            Event::getInstance()->hook(
                Event::EVENT_REFERRER_VIP,
                [
                    'user_id'               => $this->getOrder()->user_id,
                    'referrer_id'           => $this->getMember()->referrer_id,
                    'secondary_referrer_id' => $this->getMember()->secondary_referrer_id,
                    'order_id'              => $this->getOrder()->id,
                    'order_amount'          => $this->getOrder()->amount,
                ]
            );
            //订单回调
            if($this->getOrder()->callback>0) {
                Event::getInstance()->hook(
                    Event::EVENT_ORDER_CALLBACK,
                    [
                        'user_id'             => $this->getOrder()->user_id,
                        'order_id'            => $this->getOrder()->id,
                        'callback'            => $this->getOrder()->callback,
                        'change_device_id'    => $this->getOrder()->change_device_id,
                        'change_device_name'  => $this->getOrder()->change_device_name,
                        'change_device_phone' => $this->getOrder()->change_device_phone,
                    ]
                );
            }

            DbManager::getInstance()->commitWithCount('write');

            return $this->success();
        } catch (\Throwable $e) {
            DbManager::getInstance()->rollbackWithCount('write');
            throw $e;
        }
    }


    /**
     * @return OrderModel
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \Throwable
     */
    public function getOrder()
    {
        if ($this->_orderModel === null) {
            $outTradeNo = $this->notifyData->get('out_trade_no');
            $this->_orderModel = OrderModel::getOne(['id' => $outTradeNo]);
        }
        return $this->_orderModel;
    }

    public function getPayment()
    {
        if ($this->_paymentModel === null) {
            $payment_id = $this->notifyData->get('payment_id');
            $this->_paymentModel = CollectionAccountModel::getOne(['id' => $payment_id]);
        }
        return $this->_paymentModel;
    }
    public function getMember()
    {
        if ($this->_memberModel === null) {
            $user_id = $this->getOrder()->user_id;
            $this->_memberModel = MemberModel::getOne(['id' => $user_id]);
        }
        return $this->_memberModel;
    }

}
